#include "accelerometer.h"

#include "count.h"
#include "display.h"
#include "h01.h"
#include "iic.h"
#include "power.h"
#include <stm32f10x_it.h>
#include "usb.h"
#include "vx.h"

static ubyte	acc,tap;

//------------------------------------------------------------------------------

void EXTI0_IRQHandler(void){
	if(EXTI_GetITStatus(EXTI_WKUP)!=RESET){
		acc=1;
		EXTI_ClearITPendingBit(EXTI_WKUP);
	}
}
void EXTI15_10_IRQHandler(void){
	if(EXTI_GetITStatus(EXTI_GSINT)!=RESET){
		tap=1;
		EXTI_ClearITPendingBit(EXTI_GSINT);
	}
}

//------------------------------------------------------------------------------

void deinitAccelerometer(void){
	static ubyte ctrl[]={
		0xb1,	// ctrl2: hp-filter on is1
		0x80,	// ctrl3: aoi1 on int1
	};
	static ubyte int1[]={
		0x2a,	// cfg: xyz up
		0,		// src: dummy
		0x00,	// ths: 0
		0x00,	// duration: 0
	};
	waitIIC();
	writeIIC(ADD_ACC,REG_CTRL2|0x80,ctrl,2);
	waitIIC();
	writeIIC(ADD_ACC,REG_INTCFG|0x80,int1,4);
	waitIIC();
}
void fifoOff(void){
	static ubyte fifo[2]={
		0,				// ctrl: reset
		0x84			// ctrl: stream mode, ths 4
	};
	writeIIC(ADD_ACC,REG_FIFOCTRL,fifo,2);
	waitIIC();
}
void fifoOn(void){
	static ubyte fifo[2]={
		0,				// ctrl: reset
		0x9e			// ctrl: stream mode, ths 30
	};
	writeIIC(ADD_ACC,REG_FIFOCTRL,fifo,2);
	waitIIC();
}
ubyte getStatus(void){
	return getStatusEx(count);
}
ubyte getStatusEx(AccProc accproc){
	static byte	c=COUNT_SEARCHING;
	if(tap){
		tap=0;
		return STATUS_TAP;
	}
	if(acc){
		acc=0;
		ubyte n;
		readIIC(ADD_ACC,REG_FIFOSRC,&n,1);
		waitIIC();
		n&=0x1f;
		if(n){
			struct{short x,y,z;}dat;
			readIIC(ADD_ACC,REG_OUTXL|0x80,(ubyte*)&dat,6);
			waitIIC();
			for(n--;n;n--){
				int x=dat.x,y=dat.y,z=dat.z;
				readIIC(ADD_ACC,REG_OUTXL|0x80,(ubyte*)&dat,6);
				c=accproc(x,y,z,c);
				waitIIC();
			}
			c=accproc(dat.x,dat.y,dat.z,c);
			BKP_WriteBackupRegister(BACKUP_STEPS,curSteps);
			ushort ex=curSteps>>16;
			BKP_WriteBackupRegister(BACKUP_EXTRA,ex);

			IWDG_ReloadCounter();	// feed dog
			if(savRam.timeOfs){
				if(((RTC_GetCounter()+savRam.timeOfs)/3600)%24)
					clrSteps=1;
				else if(clrSteps){
					reports.yestdayLoV=curSteps;
					reports.yestdayHiV=curSteps>>16;
					curSteps=0;
					clrSteps=0;
				}
			}
		}
	}
	if(GPIO_ReadInputDataBit(GPIOC,PIN_CHIN)){
		usbOff();
		return c==COUNT_STANDBY?STATUS_STANDBY:STATUS_SILENT;
	}
	usbOn();
	return STATUS_CHARGING;
}
void initAccelerometer(void){
	static ubyte ctrl[]={
		0x47,			// ctrl1: 50-Hz, enable xyz
		0xc4,			// ctrl2: hp-filter on tap
		0x04,			// ctrl3: fifo watermark on int1
		0x10,			// ctrl4: continuos update, lsb, 4g
		0x40,			// ctrl5: fifo on, int not latched
		0x80			// ctrl6: tap enabled, active-hi
	};
	static ubyte tap[]={
		0x01,			// cfg: x single tapup
		0,				// src: dummy
		0x7f,			// ths: 0x7f
		0x08,			// timelimit: 8
	};
	initIIC();
	waitIIC();
	writeIIC(ADD_ACC,REG_CTRL1|0x80,ctrl,6);
	waitIIC();
	fifoOn();
	writeIIC(ADD_ACC,REG_TAPCFG|0x80,tap,4);
	waitIIC();
}
void pedometer(void){
	if(lowPower)
		status=STATUS_STANDBY;
	else{
		timer=0;
		displayOn();
		meterOn();
		uint t=curSteps;
		while(status==STATUS_PEDOMETER){
			if(powerSignal())
				status=STATUS_POWERDOWN;
			else{
				outDec(t);
				__WFI();
				ubyte s=getStatus();
				if(s==STATUS_TAP && timer>TIME_TAP)
					status=STATUS_CLOCK;
				else if(timer>=1999)
					status=s;
			}
		}
		meterOff();
	}
}